package com.pc.admin.strategy.factory;

import com.pc.admin.annotation.Limiting;
import com.pc.admin.entity.FrequencyEntity;
import com.pc.admin.eunms.ErrorEnum;
import com.pc.admin.exception.NoSuchStrategyException;
import com.pc.admin.strategy.FrequencyStrategy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 限流策略工厂
 *
 * @author <a href="https://www.lvfeiy.top">lfy</a>
 * @date 2023/6/23 19:11
 */
public class FrequencyFactory {

    private static volatile FrequencyFactory factory;

    private final List<FrequencyStrategy> frequencyStrategyList = new CopyOnWriteArrayList<>();

    /**
     * 单例
     */
    public static FrequencyFactory getInstance() {

        if (null == factory) {
            synchronized (FrequencyFactory.class) {
                if (null == factory) {
                    factory = new FrequencyFactory();
                }
            }
        }
        return factory;
    }

    /**
     * 获取策略
     *
     * @param limiting  限流注解
     * @param joinPoint 方法切面
     * @return 实体
     */
    public FrequencyEntity getFrequency(Limiting limiting, ProceedingJoinPoint joinPoint) {

        FrequencyStrategy frequencyStrategy = null;

        if (CollectionUtils.isEmpty(frequencyStrategyList)) {
            throw new NoSuchStrategyException(ErrorEnum.BusinessErrorEnum.STRATEGY_ERROR);
        }

        for (FrequencyStrategy strategy : frequencyStrategyList) {
            if (strategy.analysis(limiting.target())) {
                frequencyStrategy = strategy;
            }
        }

        if (null == frequencyStrategy) {
            throw new NoSuchStrategyException(ErrorEnum.BusinessErrorEnum.STRATEGY_ERROR);
        }

        return frequencyStrategy.service(limiting, joinPoint);

    }

    /**
     * 注册进工厂
     */
    public void register(FrequencyStrategy strategy) {
        this.frequencyStrategyList.add(strategy);
    }
}
